跳到主要内容

Git 远程库操作

拉取远程库

# 克隆项目
git clone 远程地址

设置代理

git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

git config --global --unset http.proxy
git config --global --unset https.proxy

远程分支

上面的 git clone 命令执行后,你可能注意到的第一个事就是在我们的本地仓库多了一个名为 o/master 的分支, 这种类型的分支就叫远程分支。由于远程分支的特性导致其拥有一些特殊属性。

注:上面的 o/master 就是 origin/master

远程分支反映了远程仓库(在你上次和它通信时)的状态。这会有助于你理解本地的工作与公共工作的差别 —— 这是你与别人分享工作成果前至关重要的一步。

远程分支有一个特别的属性,在你 checkout 时自动进入分离 HEAD 状态。Git 这么做是出于不能直接在这些分支上进行操作的原因, 你必须在别的地方完成你的工作, (更新了远程分支之后)再用远程分享你的工作成果。

远程分支有一个命名规范 —— 它们的格式是:

<remote name>/<branch name>

如果 checkout 远程分支会怎么样?

git checkout o/master
git commit

正如你所见,Git 变成了分离 HEAD 状态,当添加新的提交时 o/master 也不会更新。这是因为 o/master 只有在远程仓库中相应的分支更新了以后才会更新。

添加与移除远程库

添加别名(因为地址很长,所有一般会创建一个别名代表地址)

# 语法
git remote add 地址的别名 地址的链接

# 显示所有的地址别名
git remote -v

# 同时添加到一个远程库里面
git remote add origin git@github.com:alsritter/Treffen.git
git remote set-url --add origin git@gitee.com:alsritter/treffen.git

# 移除远程仓库
git remote rm origin

下面的 git remote add 用于添加一个全新的远程仓库,而 git remote set-url --add 用于在已有的远程仓库名称下添加额外的 URL。后者在你想要同一仓库能够推送到多个远程地址时特别有用,但请注意,即使添加了多个 URL,git push 命令仍然只会推送到第一个 URL;你需要用特定的命令来推送到其他的 URL。

同时向多个远程仓库

可以使用 git remote add 命令来添加新的远程仓库。

例如,如果你有两个远程仓库,分别命名为 originupstream,你可以这样设置:

git remote add origin <url-to-origin-repository>
git remote add upstream <url-to-upstream-repository>

要同时推送到多个远程仓库,你可以写一个简单的脚本或者使用 Git 钩子,或者为每个远程仓库单独推送。Git 本身不直接支持一条命令推送到多个远程仓库,但你可以通过几种方式来实现。

1、单独推送:这是最直接的方法,对每个远程仓库使用 git push

git push origin main
git push upstream main

2、脚本化:你可以写一个脚本来推送到所有的远程仓库:

#!/bin/sh
REMOTES="origin upstream"
for remote in $REMOTES; do
git push $remote main
done

3、Git别名:你也可以设置一个 Git 别名来执行这个操作:

git config --global alias.pushall '!git remote | xargs -L1 git push --all'

之后你可以简单地运行 git pushall 来推送所有分支到所有远程仓库。

4、使用 post-receive 钩子:如果你有权限配置服务器端的 Git 钩子,你可以在主仓库上设置一个 post-receive 钩子,当主仓库收到推送时,自动再推送到其他仓库。

注意,当你向多个远程仓库推送时,需要确保所有的远程仓库都能够接受你的更改,并且分支状态允许推送(例如,没有冲突或受保护的分支)。

另外,如果你需要经常进行这样的操作,可能需要考虑重新评估你的工作流程,看是否有更好的方式来同步你的代码,比如通过持续集成/持续部署(CI/CD)系统来自动化这一流程。

Git Push 推送分支

git push 负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。

注意:git push 不带任何参数时的行为与 Git 的一个名为 push.default 的配置有关。

# 推送分支(如果是 origin 可以直接省略)
git push origin master

如果推送失败,检查一下是否有本地公钥 find ~/.shh 如果没有则看这篇 Git配置生成密钥连接 Github

解决冲突

假设你周一克隆了一个仓库,然后开始研发某个新功能。到周五时,你新功能开发测试完毕,可以发布了。但是 —— 天啊!你的同事这周写了一堆代码,还改了许多你的功能中使用的 API,这些变动会导致你新开发的功能变得不可用。但是他们已经将那些提交推送到远程仓库了,因此你的工作就变成了基于项目旧版的代码,与远程仓库最新的代码不匹配了。

这种情况下,git push 就不知道该如何操作了。如果你执行 git push,Git 应该让远程仓库回到星期一那天的状态吗?还是直接在新代码的基础上添加你的代码,异或由于你的提交已经过时而直接忽略你的提交?

因为这情况有许多的不确定性,Git 是不会允许你 push 变更的。实际上它会强制你先合并远程最新的代码,然后才能分享你的工作。

如下图可见,本地的远程分支的指针还在 C1 而远程的指针已经指向 C2 了,所以这样是无法提交的

通过 Rebase 的方式提交

这时如果执行:

git fetch
git rebase o/master
git push

git fetch 更新了本地仓库中的远程分支,然后用 rebase 将我们的工作移动到最新的提交记录下,最后再用 git push 推送到远程仓库。

或者使用这个简写命令

# 等价于上面三个命令
git pull --rebase
git push

通过 Merge 的方式提交

尽管 git merge 不会移动你的工作(它会创建新的合并提交),但是它会告诉 Git 你已经合并了远程仓库的所有变更。这是因为远程分支现在是你本地分支的祖先,也就是说你的提交已经包含了远程分支的所有变化。

这时如果执行:

git fetch
git merge o/master
git push

很好!但是要敲那么多命令,有没有更简单一点的?

前面已经介绍过 git pull 就是 fetch 和 merge 的简写,类似的 git pull --rebase 就是 fetch 和 rebase 的简写!

强制提交

最后的手段:暴力解决冲突

# 平时不要用这个,这个是强制 push,会使远程库文件丢失
git push -u origin master -f

Reference